from django.db import transaction
from rest_framework import serializers
from apps.goods.models import SKU, SKUSpecification, GoodsCategory, SPU, SpecificationOption, SPUSpecification
from celery_tasks.html.tasks import generate_static_sku_detail_html

class SpecOptSimpleSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = [
            'id',
            'value'
        ]



class SPUSpecModelSerializer(serializers.ModelSerializer):
    spu = serializers.StringRelatedField()
    spu_id = serializers.IntegerField()

    # 关联从表SpecficationOption多条数据
    options = SpecOptSimpleSerializer(many=True)

    class Meta:
        model = SPUSpecification
        fields = [
            'id',
            'name',
            'spu',
            'spu_id',
            'options'
        ]

class  SKUSpecOptModelSerializer(serializers.ModelSerializer):
    # 因为这2个字段必须参与反序列化，所有我们只能手动映射覆盖原有的默认映射(默认只作用于序列化)
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()
    class Meta:
        model = SKUSpecification
        fields = ['spec_id', 'option_id']

class SKUModelSerializer(serializers.ModelSerializer):
    # 三个隐藏字段：
    # 1、本表主键id，会自动映射
    # 2、外间关联对象的主键隐藏字段(如：spu_id), 不会自动映射
    spu = serializers.StringRelatedField()
    spu_id = serializers.IntegerField()
    category = serializers.StringRelatedField()
    category_id = serializers.IntegerField()

    # 3、从表related_name指定的主表隐藏字段，不会自动映射
    specs = SKUSpecOptModelSerializer(many=True)
    class Meta:
        model = SKU
        fields = "__all__"

    def create(self, validated_data):

        # 将原来的specs, pop()出来
        specs = validated_data.pop("specs")

        with transaction.atomic():
            save_id = transaction.savepoint()
            try:

                # 创建主表数据
                sku = SKU.objects.create(**validated_data)

                # 新建从表数据
                for temp in specs:
                    # 先加入sku_id这个键
                    temp['sku_id'] = sku.id
                    # 创建数据
                    SKUSpecification.objects.create(**temp)
            except Exception as e:
                transaction.savepoint_rollback(save_id)
                raise serializers.ValidationError("数据库连接失败")

            transaction.savepoint_commit(save_id)

        generate_static_sku_detail_html.delay(sku.id)

        return sku

    def update(self, instance, validated_data):
        # 将原来的specs, pop()出来
        specs = validated_data.pop("specs")

        # 更新主表数据：调用父类的update方法进行更新
        sku = super().update(instance, validated_data)

        # 删除原来中间表的数据
        SKUSpecification.objects.filter(sku_id=sku.id).delete()

        # 新建新的数据
        for temp in specs:
            temp['sku_id'] = sku.id
            SKUSpecification.objects.create(**temp)

        return sku



class SKUCategorySimpleSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = [
            'id',
            'name'
        ]


class SPUSimpleSerializer(serializers.ModelSerializer):
    class Meta:
        model = SPU
        fields = [
            'id',
            'name'
        ]


